/*
 * ClientBaru.java
 *
 * Created on Apr 9, 2011, 6:54:58 PM
 */
package bitetorrent.form;

import bitetorrent.Torrent;
import bitetorrent.model.AddressPort;
import bitetorrent.model.FileDownloader;
import bitetorrent.model.Global;
import bitetorrent.peersComm.P2PClient;
import bitetorrent.trackerComm.TrackerHandler;
import bitetorrent.peersComm.PeerListener;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author Robert Gunawan
 */
public class ClientBaru extends javax.swing.JFrame {

    public String port = "10000";
    /** Creates new form ClientBaru */
    public int selected = -999;
    ArrayList<Torrent> arrayTorrent = new ArrayList<Torrent>();
    ArrayList<TrackerHandler> handlers = new ArrayList<TrackerHandler>();
    PeerListener clientListener = new PeerListener(10000);
    Setting setting;

    public ClientBaru() {
        initComponents();
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();

        // Determine the new location of the window
        int w = this.getSize().width;
        int h = this.getSize().height;
        int x = (dim.width - w) / 2;
        int y = (dim.height - h) / 2;

        // Move the window
        this.setLocation(x, y);

        // Run Listener
        clientListener.start();

        // Create Setting
        setting = new Setting();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        canvas1 = new java.awt.Canvas();
        choice1 = new java.awt.Choice();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        jScrollPane2 = new javax.swing.JScrollPane();
        Tabel = new javax.swing.JTable();
        Start = new javax.swing.JButton();
        Pause = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        Resume = new javax.swing.JButton();
        Log = new java.awt.List();
        jMenuBar1 = new javax.swing.JMenuBar();
        File = new javax.swing.JMenu();
        CreateTorrent = new javax.swing.JMenuItem();
        AddTorrent = new javax.swing.JMenuItem();
        Option = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null},
                {null, null, null, null}
            },
            new String [] {
                "Title 1", "Title 2", "Title 3", "Title 4"
            }
        ));
        jScrollPane1.setViewportView(jTable1);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Client Form");

        jScrollPane2.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jScrollPane2MouseClicked(evt);
            }
        });
        jScrollPane2.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                jScrollPane2FocusGained(evt);
            }
        });

        Tabel.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Filename", "Size", "Downloaded"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.Integer.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                true, false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        Tabel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                TabelMouseClicked(evt);
            }
        });
        jScrollPane2.setViewportView(Tabel);
        Tabel.getColumnModel().getColumn(0).setResizable(false);
        Tabel.getColumnModel().getColumn(1).setResizable(false);
        Tabel.getColumnModel().getColumn(2).setResizable(false);

        Start.setText("Start");
        Start.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                StartActionPerformed(evt);
            }
        });

        Pause.setText("Pause");

        jButton3.setText("Delete");
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton3ActionPerformed(evt);
            }
        });

        Resume.setText("Resume");

        File.setText("File");
        File.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                FileActionPerformed(evt);
            }
        });

        CreateTorrent.setText("Create Torrent");
        CreateTorrent.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                CreateTorrentActionPerformed(evt);
            }
        });
        File.add(CreateTorrent);

        AddTorrent.setText("Add Torrent");
        AddTorrent.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                AddTorrentActionPerformed(evt);
            }
        });
        File.add(AddTorrent);

        jMenuBar1.add(File);

        Option.setText("Option");

        jMenuItem1.setText("Change Port");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        Option.add(jMenuItem1);

        jMenuBar1.add(Option);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(layout.createSequentialGroup()
                            .addContainerGap()
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                            .addComponent(Start)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(Pause)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(Resume)
                            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                            .addComponent(jButton3)))
                    .addGroup(layout.createSequentialGroup()
                        .addContainerGap()
                        .addComponent(Log, javax.swing.GroupLayout.DEFAULT_SIZE, 452, Short.MAX_VALUE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(40, 40, 40)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jButton3)
                    .addComponent(Pause)
                    .addComponent(Start)
                    .addComponent(Resume))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 127, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(Log, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem1ActionPerformed
        // TODO add your handling code here:
        PortChanger a = new PortChanger(this, true);
        a.Port.setText(port);
        a.show();

    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void CreateTorrentActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_CreateTorrentActionPerformed
        // TODO add your handling code here:
        CreateTorrentForm a = new CreateTorrentForm(this, true);
        a.show();
    }//GEN-LAST:event_CreateTorrentActionPerformed

    private void FileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_FileActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_FileActionPerformed

    private void AddTorrentActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_AddTorrentActionPerformed
        try {
            // TODO add your handling code here:
            /*
             * KAMUS LOKAL
             */
            String namaFile = null;
            /*
             * ALGORITMA
             */
            // Open JFileChooser
            JFileChooser Open = new JFileChooser();
            // Set Filter
            /*Open.setFileFilter(new FileFilter() {
            public boolean accept(File f) {
            return f.getName().toLowerCase().endsWith(".torrent")
            || f.isDirectory();
            }
            public String getDescription() {
            return "torrent files";
            }
            });*/
            // Set Current Directory
            Open.setCurrentDirectory(new File(""));
            int retval = Open.showOpenDialog(this);
            if (retval == JFileChooser.APPROVE_OPTION) {
                File F = Open.getSelectedFile();
                namaFile = F.getAbsolutePath();
                // Disimpan dalam Object Torrent
                Torrent torrent = new Torrent();
                torrent.ReadTorrent(namaFile);
                // Masukkan ke arrayTorrent
                arrayTorrent.add(torrent);
                selected = arrayTorrent.size() - 1; // update selected
                //masukkan ke tabel
                String[] aaa = new String[3];
                aaa[0] = arrayTorrent.get(selected).fileName;
                aaa[1] = "" + arrayTorrent.get(selected).fileLength;
                aaa[2] = "0%";
                ((DefaultTableModel) Tabel.getModel()).addRow(aaa);
                //masukkan ke log
                Log.add("Add file: " + arrayTorrent.get(selected).fileName + " size: " + arrayTorrent.get(selected).fileLength + " announcer: " + arrayTorrent.get(selected).announce);
            } // Read and Parse File     
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(ClientBaru.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(ClientBaru.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//GEN-LAST:event_AddTorrentActionPerformed

    private void StartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_StartActionPerformed
        // TODO add your handling code here:
        if (selected >= 0) {
            try {
                startDownload();
            } catch (IOException ex) {
                Logger.getLogger(ClientBaru.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            // Terdapat kesalahan
            JOptionPane.showMessageDialog(this, "No File selected!");

        }
    }//GEN-LAST:event_StartActionPerformed

    private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton3ActionPerformed
        // TODO add your handling code here:
        if (selected >= 0) //valid
        {
            Log.add("Removing " + arrayTorrent.get(selected).fileName + " with announcer " + arrayTorrent.get(selected).announce + " from torrent list");
            arrayTorrent.remove(selected);
            ((DefaultTableModel) Tabel.getModel()).removeRow(selected);
            selected = -999;
            Tabel.clearSelection();
            //((DefaultTableModel) Tabel.getModel()).
            //Tabel.setSelectionMode(selected-1);
        } else {
            JOptionPane.showMessageDialog(this, "No File Selected!");
        }
    }//GEN-LAST:event_jButton3ActionPerformed

    private void jScrollPane2FocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_jScrollPane2FocusGained
        // TODO add your handling code here:
    }//GEN-LAST:event_jScrollPane2FocusGained

    private void jScrollPane2MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jScrollPane2MouseClicked
        // TODO add your handling code here:
        //JOptionPane.showMessageDialog(this, "click");
    }//GEN-LAST:event_jScrollPane2MouseClicked

    private void TabelMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_TabelMouseClicked
        // TODO add your handling code here:
        selected = Tabel.getSelectedRow();
    }//GEN-LAST:event_TabelMouseClicked

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new ClientBaru().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem AddTorrent;
    private javax.swing.JMenuItem CreateTorrent;
    private javax.swing.JMenu File;
    private java.awt.List Log;
    private javax.swing.JMenu Option;
    private javax.swing.JButton Pause;
    private javax.swing.JButton Resume;
    private javax.swing.JButton Start;
    private javax.swing.JTable Tabel;
    private java.awt.Canvas canvas1;
    private java.awt.Choice choice1;
    private javax.swing.JButton jButton3;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JTable jTable1;
    // End of variables declaration//GEN-END:variables

    private void startDownload() throws IOException {
        // Ambil object torrent
        Torrent torrent = arrayTorrent.get(selected);

        // Buat thread untuk melakukan request ke tracker
        TrackerHandler handler = new TrackerHandler(torrent);
        FileDownloader fd = new FileDownloader(torrent);

        handlers.add(handler);
        Global.fileDownloads.add(fd);
        handler.start();
        try {
            Thread.sleep(200);
        } catch (InterruptedException ex) {
            Logger.getLogger(ClientBaru.class.getName()).log(Level.SEVERE, null, ex);
        }

        createClients(fd, handler);

        // Tulis ke log
        Log.add("Now is Downloading " + torrent.fileName);
    }

    private void createClients(FileDownloader fd, TrackerHandler handler) {
        System.out.println("Create client peer.");
        while (true) {
            try {
                if (handler.response != null && handler.response.peers != null && handler.response.peers.size() > 0) {
                    for (int i = 0; i < handler.response.peers.size(); ++i) {
                        AddressPort addPort = handler.response.peers.get(i);
                        System.out.println("Create socket to ." + addPort.address + ":" + addPort.port);
                        Socket s = new Socket(addPort.address, Integer.parseInt(addPort.port));
                        System.out.println("Connected to " + addPort.address + ":" + addPort.port);
                        P2PClient client = new P2PClient(s, fd);
                        client.start();
                        Global.p2PClientContainer.add(client);
                    }
                    return;
                }
                System.out.println("Wait response.");
                Thread.sleep(100);
            } catch (IOException ex) {
                Logger.getLogger(ClientBaru.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InterruptedException ex) {
                Logger.getLogger(ClientBaru.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}
